home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
os2
/
plnk081.zip
/
pilot-link.0.8.1
/
pilot-xfer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-10
|
14KB
|
618 lines
/* pilot-xfer.c: Pilot Database transfer utility
*
* (c) 1996, Kenneth Albanowski.
*
* This is free software, licensed under the GNU Public License V2.
* See the file COPYING for details.
*/
#include <stdio.h>
#ifdef __EMX__
#include <getopt.h>
#include <sys/types.h>
#endif
#include <sys/stat.h>
#include <signal.h>
#include "pi-source.h"
#include "pi-socket.h"
#include "pi-file.h"
#include "pi-dlp.h"
#define pi_mktag(c1,c2,c3,c4) (((c1)<<24)|((c2)<<16)|((c3)<<8)|(c4))
int sd = 0;
char * device = "/dev/pilot";
char * progname;
char * exclude[100];
int numexclude = 0;
RETSIGTYPE SigHandler(int signal);
void MakeExcludeList(char *efile) {
char temp[1024];
FILE *f = fopen(efile,"r");
while((fgets(temp,sizeof(temp),f)) != NULL) {
if (temp[strlen(temp)-1] == '\n')
temp[strlen(temp)-1] = '\0';
printf("Will exclude: %s\n",temp);
exclude[numexclude++] = strdup(temp);
}
}
void Connect(void) {
struct pi_sockaddr addr;
int ret;
if (sd!=0)
return;
signal(SIGHUP, SigHandler);
signal(SIGINT, SigHandler);
signal(SIGSEGV, SigHandler);
if (!(sd = pi_socket(PI_AF_SLP, PI_SOCK_STREAM, PI_PF_PADP))) {
perror("pi_socket");
exit(1);
}
addr.pi_family = PI_AF_SLP;
strcpy(addr.pi_device,device);
ret = pi_bind(sd, (struct sockaddr*)&addr, sizeof(addr));
if(ret == -1) {
fprintf(stderr, "Unable to bind to port '%s'.\n(Please see '%s -h' for information setting the port).\n", device, progname);
exit(1);
}
printf("Waiting for connection on %s (press the HotSync button now)...\n", device);
ret = pi_listen(sd,1);
if(ret == -1) {
perror("pi_listen");
exit(1);
}
sd = pi_accept(sd,0,0);
if(sd == -1) {
perror("pi_accept");
exit(1);
}
puts("Connected");
}
void Disconnect(void)
{
if(sd==0)
return;
dlp_EndOfSync(sd, 0);
pi_close(sd);
sd = 0;
}
RETSIGTYPE SigHandler(int signal)
{
puts("Abort on signal!");
Disconnect();
exit(3);
}
void VoidSyncFlags(void)
{
struct PilotUser U;
Connect();
if (dlp_ReadUserInfo(sd, &U)>=0) {
U.lastSyncPC = 0x00000000; /* Hopefully unique constant, to tell
any Desktop software that databases
have been altered, and that a slow
sync is necessary */
U.lastSyncDate = U.successfulSyncDate = time(0);
dlp_WriteUserInfo(sd, &U);
}
}
void Backup(char * dirname)
{
int i;
Connect();
mkdir(dirname,0700);
i = 0;
for(;;) {
struct DBInfo info;
struct pi_file * f;
int x;
int skip = 0;
char name[256];
if (dlp_OpenConduit(sd)<0) {
puts("Exiting on cancel, all data _not_ backed up.");
exit(1);
}
if( dlp_ReadDBList(sd, 0, 0x80, i, &info) < 0)
break;
i = info.index + 1;
for(x = 0; x < numexclude; x++) {
/* printf("Skipcheck:%s:%s:\n",exclude[x],info.name); */
if(strcmp(exclude[x],info.name) == 0) {
printf("Excluding '%s'...\n",info.name);
skip = 1;
}
}
if(skip == 1)
continue;
sprintf(name, "%s/%s", dirname, info.name);
if (info.flags & dlpDBFlagResource)
strcat(name,".prc");
else
strcat(name,".pdb");
printf("Backing up '%s'... ", name);
fflush(stdout);
/* Ensure that DB-open flag is not kept */
info.flags &= 0xff;
f = pi_file_create(name, &info);
if (f==0) {
printf("Failed, unable to create file\n");
break;
}
if(pi_file_retrieve(f, sd, 0)<0)
printf("Failed, unable to back up database\n");
else
printf("OK\n");
pi_file_close(f);
}
printf("Backup done.\n");
}
void Fetch(char * dbname)
{
struct DBInfo info;
char name[256];
struct pi_file * f;
Connect();
if (dlp_OpenConduit(sd)<0) {
puts("Exiting on cancel, all data _not_ backed up.");
exit(1);
}
if (dlp_FindDBInfo(sd, 0, 0, dbname, 0, 0, &info)<0) {
printf("Unable to locate database '%s', fetch skipped.\n", dbname);
return;
}
strcpy(name, dbname);
if (info.flags & dlpDBFlagResource)
strcat(name,".prc");
else
strcat(name,".pdb");
printf("Fetching '%s'... ", name);
fflush(stdout);
info.flags &= 0xff;
f = pi_file_create(name, &info);
if (f==0) {
printf("Failed, unable to create file\n");
return;
}
if(pi_file_retrieve(f, sd, 0)<0)
printf("Failed, unable to back up database\n");
else
printf("OK\n");
pi_file_close(f);
printf("Fetch done.\n");
}
void Delete(char * dbname)
{
struct DBInfo info;
Connect();
if (dlp_OpenConduit(sd)<0) {
puts("Exiting on cancel, all data _not_ backed up.");
exit(1);
}
dlp_FindDBInfo(sd, 0, 0, dbname, 0, 0, &info);
printf("Deleting '%s'... ", dbname);
if (dlp_DeleteDB(sd, 0, dbname)>=0) {
if (info.type == pi_mktag('b','o','o','t')) {
printf(" (rebooting afterwards) ");
}
printf("OK\n");
} else {
printf("Failed, unable to delete database\n");
}
fflush(stdout);
printf("Delete done.\n");
}
struct db {
char name[256];
int flags;
unsigned long creator;
unsigned long type;
int maxblock;
};
int compare(struct db * d1, struct db * d2)
{
/* types of 'appl' sort later then other types */
if(d1->creator == d2->creator)
if(d1->type != d2->type) {
if(d1->type == pi_mktag('a','p','p','l'))
return 1;
if(d2->type == pi_mktag('a','p','p','l'))
return -1;
}
return d1->maxblock < d2->maxblock;
}
void Restore(char * dirname)
{
DIR * dir;
struct dirent * dirent;
struct DBInfo info;
struct db * db[256];
int dbcount = 0;
int i,j,max,size;
struct pi_file * f;
dir = opendir(dirname);
while( (dirent = readdir(dir)) ) {
char name[256];
if (dirent->d_name[0] == '.')
continue;
db[dbcount] = (struct db*)malloc(sizeof(struct db));
sprintf(db[dbcount]->name, "%s/%s", dirname, dirent->d_name);
f = pi_file_open(db[dbcount]->name);
if (f==0) {
printf("Unable to open '%s'!\n", name);
break;
}
pi_file_get_info(f, &info);
db[dbcount]->creator = info.creator;
db[dbcount]->type = info.type;
db[dbcount]->flags = info.flags;
db[dbcount]->maxblock = 0;
pi_file_get_entries(f, &max);
for (i=0;i<max;i++) {
if (info.flags & dlpDBFlagResource)
pi_file_read_resource(f, i, 0, &size, 0, 0);
else
pi_file_read_record(f, i, 0, &size, 0, 0,0 );
if (size > db[dbcount]->maxblock)
db[dbcount]->maxblock = size;
}
pi_file_close(f);
dbcount++;
}
closedir(dir);
#ifdef DEBUG
printf("Unsorted:\n");
for (i=0;i<dbcount;i++) {
printf("%d: %s\n", i, db[i]->name);
printf(" maxblock: %d\n", db[i]->maxblock);
printf(" creator: '%s'\n", printlong(db[i]->creator));
printf(" type: '%s'\n", printlong(db[i]->type));
}
#endif
for (i=0;i<dbcount;i++)
for (j=i+1;j<dbcount;j++)
if (compare(db[i],db[j])>0) {
struct db * temp = db[i];
db[i] = db[j];
db[j] = temp;
}
#ifdef DEBUG
printf("Sorted:\n");
for (i=0;i<dbcount;i++) {
printf("%d: %s\n", i, db[i]->name);
printf(" maxblock: %d\n", db[i]->maxblock);
printf(" creator: '%s'\n", printlong(db[i]->creator));
printf(" type: '%s'\n", printlong(db[i]->type));
}
#endif
Connect();
for (i=0;i<dbcount;i++) {
if ( dlp_OpenConduit(sd) < 0) {
puts("Exiting on cancel. All data not restored.");
exit(1);
}
f = pi_file_open(db[i]->name);
if (f==0) {
printf("Unable to open '%s'!\n", db[i]->name);
break;
}
printf("Restoring %s... ", db[i]->name);
fflush(stdout);
if(pi_file_install(f, sd, 0)<0)
printf("failed.\n");
else
printf("OK\n");
pi_file_close(f);
}
VoidSyncFlags();
printf("Restore done\n");
}
void Install(char * filename)
{
struct pi_file * f;
Connect();
if ( dlp_OpenConduit(sd) < 0) {
puts("Exiting on cancel. All data not restored.");
exit(1);
}
f = pi_file_open(filename);
if (f==0) {
printf("Unable to open '%s'!\n", filename);
return;
}
printf("Installing %s... ", filename);
fflush(stdout);
if(pi_file_install(f, sd, 0)<0)
printf("failed.\n");
else
printf("OK\n");
pi_file_close(f);
VoidSyncFlags();
printf("Install done\n");
}
void Merge(char * filename)
{
struct pi_file * f;
Connect();
if ( dlp_OpenConduit(sd) < 0) {
puts("Exiting on cancel. All data not restored.");
exit(1);
}
f = pi_file_open(filename);
if (f==0) {
printf("Unable to open '%s'!\n", filename);
return;
}
printf("Merging %s... ", filename);
fflush(stdout);
if(pi_file_merge(f, sd, 0)<0)
printf("failed.\n");
else
printf("OK\n");
pi_file_close(f);
VoidSyncFlags();
printf("Merge done\n");
}
void List(void)
{
struct DBInfo info;
int i;
Connect();
if ( dlp_OpenConduit(sd) < 0) {
puts("Exiting on cancel. All data not restored.");
exit(1);
}
printf("Reading list of databases...\n");
i = 0;
for(;;) {
if( dlp_ReadDBList(sd, 0, 0x80, i, &info) < 0)
break;
i = info.index + 1;
printf("'%s'\n", info.name);
}
printf("List done.\n");
}
void Purge(void)
{
struct DBInfo info;
int i;
int h;
Connect();
if ( dlp_OpenConduit(sd) < 0) {
puts("Exiting on cancel. All data not restored.");
exit(1);
}
printf("Reading list of databases to purge...\n");
i = 0;
for(;;) {
if( dlp_ReadDBList(sd, 0, 0x80, i, &info) < 0)
break;
i = info.index + 1;
if (info.flags & 1)
continue; /* skip resource databases */
printf("Purging deleted records from '%s'... ", info.name);
h = 0;
if ((dlp_OpenDB(sd, 0, 0x40|0x80, info.name, &h)>=0) &&
(dlp_CleanUpDatabase(sd, h)>=0) &&
(dlp_ResetSyncFlags(sd,h)>=0) ) {
printf("OK\n");
} else {
printf("Failed\n");
}
if (h!=0)
dlp_CloseDB(sd, h);
}
VoidSyncFlags();
printf("Purge done.\n");
}
void Help(void)
{
printf("Usage: %s [%s] command(s)\n\n",progname,TTYPrompt);
printf("Where a command is one or more of: -b(ackup) backupdir\n");
printf(" -r(estore) backupdir\n");
printf(" -i(nstall) filename(s)\n");
printf(" -m(erge) filename(s)\n");
printf(" -f(etch) dbname(s)\n");
printf(" -d(elete) dbname(s)\n");
printf(" -e(xclude) filename(s)\n");
printf(" -p(urge)\n");
printf(" -l(ist)\n");
printf("\n");
printf("The serial port to connect to may be specified by the PILOTPORT\n");
printf("environment variable instead of the command line. If not specified\n");
printf("anywhere, it will default to /dev/pilot.\n");
exit(0);
}
int main(int argc, char *argv[])
{
int c;
int lastmode = 0;
char *tmp;
#ifdef sun
extern char* optarg;
extern int optind;
#endif
progname = argv[0];
if (argc < 2) {
Help();
}
#ifdef __EMX__
device = argv[1];
#endif
tmp = getenv("PILOTPORT");
if (tmp != NULL)
device = tmp;
#ifdef __EMX__
optmode = GETOPT_KEEP;
#else
optind=1;
#endif
while (argv[optind] != NULL) {
c = getopt(argc, argv, "b:e:r:i:m:f:d:plh");
if (c == EOF) {
optarg=argv[optind++];
c = lastmode;
if (lastmode=='b' || lastmode=='r' || lastmode=='l' || lastmode=='p') {
fprintf(stderr, "'%c', only accepts one argument!\n", lastmode);
continue;
}
if (c == 0) {
device = optarg;
continue;
}
}
switch (c) {
case 'b':
Backup(optarg);
break;
case 'r':
Restore(optarg);
break;
case 'i':
Install(optarg);
break;
case 'm':
Merge(optarg);
break;
case 'f':
Fetch(optarg);
break;
case 'd':
Delete(optarg);
break;
case 'e':
MakeExcludeList(optarg);
break;
case 'p':
Purge();
break;
case 'l':
List();
break;
default:
break;
case 'h': case '?':
Help();
}
lastmode=c;
}
if (lastmode==0)
Help();
Disconnect();
exit(0);
}